package com.example.nio.tranport.mina.client;

import com.example.nio.message.Request;
import com.example.nio.message.Response;
import com.example.nio.message.ResponseFuture;
import com.example.nio.tranport.mina.factory.MinaClientFactory;
import lombok.Data;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author: chentao
 * @data 2025年02月02日 上午11:19
 */
@Data
public class MinaClientFactoryImpl extends IoHandlerAdapter implements MinaClientFactory, InitializingBean, DisposableBean {

    Logger logger = LoggerFactory.getLogger(getClass());

    private Map<String, ResponseFuture> responseFutureMap = new ConcurrentHashMap<>();

    private MinaClient minaClient;

    @Value("${mina.server.host:127.0.0.1}")
    private String host;

    @Value("${mina.server.port:8000}")
    private int port;

    @Override
    public void afterPropertiesSet() throws Exception {
        this.minaClient = new MinaClient(host, port, this);
        this.minaClient.init();
        this.minaClient.start();
    }

    @Override
    public void destroy() throws Exception {
        this.minaClient.stop();
    }

    /***
     * 发送异步请求
     *
     * @param request
     * @return
     */
    @Override
    public boolean sendAsyncRequest(Request request) throws Exception {
        IoSession ioSession = this.minaClient.getIoSession();
        if (ioSession == null) {
            throw new Exception("ioSession is null");
        }
        return ioSession.write(request).awaitUninterruptibly().isWritten();
    }

    /****
     * 发送同步请求
     *
     * @param request
     * @return
     */
    @Override
    public Response sendSynRequest(Request request) throws Exception {
        if (sendAsyncRequest(request)) {
            responseFutureMap.putIfAbsent(request.getRequestId(), new ResponseFuture(request));
        }
        return responseFutureMap.get(request.getRequestId()).getResponse();
    }

    /***
     * 处理消息
     *
     * @param session
     * @param message
     * @throws Exception
     */
    @Override
    public void messageReceived(IoSession session, Object message) throws Exception {
        logger.warn("client Received: " + message);
        if (message instanceof Response) {
            if (((Response) message).getRequest().isPing()) {
                logger.warn("client Received ping message" + message);
            } else {
                String requestId = ((Response) message).getRequest().getRequestId();
                if (responseFutureMap.containsKey(requestId)) {
                    ResponseFuture responseFuture = responseFutureMap.remove(requestId);
                    responseFuture.setResponse((Response) message);
                }
            }
        }
    }
}
